#ifndef JSONRPCMESSAGE_H
#define JSONRPCMESSAGE_H

#include <QJsonObject>
#include <QVariantList>

class JsonRpcSocket;

class JsonRpcMessage
{
public:
    enum Type{
        Notification,
        Request,
        Result,
        Error
    };

    enum ErrorCode{
        NoError = 0,
        MethodNotFound = -2000,
        DifferentSignature = -2001,
        ServiceNotFound = -2002
    };

    JsonRpcMessage() {}
    JsonRpcMessage(const JsonRpcMessage &message);
    JsonRpcMessage(const QJsonObject &obj);

    JsonRpcMessage& operator=(const JsonRpcMessage& message);

    Type type() const;
    int id() const;
    QString method() const;
    QVariantList params() const;


    /**
     * @brief JsonRpcMessage::result returns the result if the message is a response message, otherwise it returns a default constructed QVariant
     * @return the result of the request message
     */
    QVariant result() const;


    /**
     * @brief JsonRpcMessage::error returns a boolean that states whether the message is an error message or not
     * @return true if the message is an error message, otherwise returns false
     */
    bool error() const;

    /**
     * @brief JsonRpcMessage::errorCode returns the error code if the message is an error message, otherwise returns 0
     * @return the error code
     */
    int errorCode() const;

    /**
     * @brief JsonRpcMessage::errorMessage returns the error message as a QString if the message is an error message, otherwise returns an empty string
     * @return the error message
     */
    QString errorMessage() const;

    /**
     * @brief JsonRpcMessage::errorData returns the error data as a QVariant if the message is an error message, otherwise returns an default constructed QVariant
     * @return the error data
     */
    QVariant errorData() const;


    /**
     * @brief JsonRpcMessage::createRequest creates a request filled with the method name 'methodName' and the parameter list 'paramList'
     * @param methodName is the method name
     * @param paramList is the parameter list
     * @return a JsonRpcMessage representing the request
     */
    static JsonRpcMessage createRequest(const QString& methodName, const QVariantList& paramList);

    /**
     * @brief JsonRpcMessage::createNotification creates a notification message with the method name 'methoodName' and the parameter list 'paramList'
     * @param methodName is the method name
     * @param paramList is a QVariant list of all the parameters passed to the method
     * @return a JsonRpcMessage representing the notification
     */
    static JsonRpcMessage createNotification(const QString& methodName, const QVariantList& paramList);

    /**
     * @brief JsonRpcMessage::createResponse creates a response message with the result 'result'. This method writes the result in the Json object
     * @param result is the result that comes with the response
     * @return a JsonRpcMessage representing the response
     */
    JsonRpcMessage createResponse(const QVariant& result) const;


    /**
     * @brief JsonRpcMessage::createError creates an error message with error code 'code', error message 'message' and data
     * @param code is the error code
     * @param message is a short description of the error
     * @param data is the data coming with the error
     * @return a JsonRpcMessage representing the error
     */
    JsonRpcMessage createError(int code, const QString& message, const QVariant& data = QVariant()) const;

private:
    // the Json object that the message contains
    QJsonObject v_object;

    // the message type
    Type v_type;


    friend class JsonRpcSocket;

    // The unique request identifier, it is incremented every time a request is created
    static int v_uniqueIdentifier;
};

#endif // JSONRPCMESSAGE_H
